﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using Delay;

namespace lfm.Parser
{
    internal class Generic
    {
        public static async Task<List<lfm.Link>> getBuyLinks(String e)
        {
            List<lfm.Link> results = new List<lfm.Link>();

            // Make Method Run Asynchronously
            await Task.Run(() =>
            {
                XDocument x = XDocument.Parse(e);

                // Parse Physical link details
                var physical = from u in x.Element("lfm").SafeGetElement("affiliations").SafeGetElement("physicals").Descendants("affiliation")
                               select new lfm.Link
                               {
                                   SupplierName = u.SafeGetElement("supplierName").SafeGetStringValue(),
                                   Currency = u.SafeGetElement("price").SafeGetElement("currency").SafeGetStringValue(),
                                   Price = u.SafeGetElement("price").SafeGetElement("amount").SafeGetStringValue(),
                                   BuyLink = u.SafeGetElement("buyLink").SafeGetUriValue(),
                                   SupplierIcon = u.SafeGetElement("supplierIcon").SafeGetUriValue(),
                                   isSearch = Converters.ToBool(u.SafeGetElement("isSearch").SafeGetStringValue()),
                                   Medium = LinkType.physical
                               };

                foreach (var r in physical) results.Add(r);

                // Parse Physical link details
                var download = from u in x.Element("lfm").SafeGetElement("affiliations").SafeGetElement("downloads").Descendants("affiliation")
                               select new lfm.Link
                               {
                                   SupplierName = u.SafeGetElement("supplierElement").SafeGetStringValue(),
                                   Currency = u.SafeGetElement("price").SafeGetElement("currency").SafeGetStringValue(),
                                   Price = u.SafeGetElement("price").SafeGetElement("amount").SafeGetStringValue(),
                                   BuyLink = u.SafeGetElement("buyLink").SafeGetUriValue(),
                                   SupplierIcon = u.SafeGetElement("supplierIcon").SafeGetUriValue(),
                                   isSearch = Converters.ToBool(u.SafeGetElement("isSearch").SafeGetStringValue()),
                                   Medium = LinkType.download
                               };

                foreach (var r in download) results.Add(r);
            });

            // return the full album
            return results;
        }

        public static async Task<List<lfm.Shout>> getShouts(String e)
        {
            List<lfm.Shout> results = new List<lfm.Shout>();

            // Make Method Run Asynchronously
            await Task.Run(() =>
            {
                XDocument x = XDocument.Parse(e);

                var eresult = from u in x.Descendants("shout")
                              select new lfm.Shout
                              {
                                  Author = u.SafeGetElement("author").SafeGetStringValue(),
                                  Body = u.SafeGetElement("body").SafeGetStringValue(),
                                  Date = u.SafeGetElement("date").SafeGetDateTimeValue(DateTime.Now)
                              };

                foreach (var i in eresult) results.Add(i);
            });

            return results;
        }

        public static async Task<List<lfm.Tag>> getTags(String e)
        {
            List<lfm.Tag> results = new List<lfm.Tag>();

            // Make Method Run Asynchronously
            await Task.Run(() =>
            {
                XDocument x = XDocument.Parse(e);

                var eresult = from u in x.Descendants("tag")
                              select new lfm.Tag
                              {
                                  Name = u.SafeGetElement("name").SafeGetStringValue(),
                                  URL = u.SafeGetElement("url").SafeGetUriValue(),
                                  Count = u.SafeGetElement("count").SafeGetInt64Value()
                              };

                foreach (var i in eresult) results.Add(i);
            });

            return results;
        }

        public static async Task<List<lfm.Tag>> getFullTags(String e)
        {
            List<lfm.Tag> results = new List<lfm.Tag>();

            // Make Method Run Asynchronously
            await Task.Run(() =>
            {
                XDocument x = XDocument.Parse(e);

                var eresult = from u in x.Descendants("tag")
                              select new lfm.Tag
                              {
                                  Name = u.SafeGetElement("name").SafeGetStringValue(),
                                  URL = u.SafeGetElement("url").SafeGetUriValue(),
                                  Reach = u.SafeGetElement("reach").SafeGetInt64Value(),
                                  Taggings = u.SafeGetElement("taggings").SafeGetInt64Value(),
                                  Streamable = Converters.ToBool(u.SafeGetElement("streamable").SafeGetStringValue()),
                                  WikiPublished = u.SafeGetElement("wiki").SafeGetElement("published").SafeGetDateTimeValue(DateTime.Now),
                                  WikiSummary = u.SafeGetElement("wiki").SafeGetElement("summary").SafeGetStringValue(),
                                  WikiContent = u.SafeGetElement("wiki").SafeGetElement("content").SafeGetStringValue()
                              };

                foreach (var i in eresult) results.Add(i);
            });

            return results;
        }

        public static async Task<List<lfm.Track>> getTracks(String e)
        {
            List<lfm.Track> result = new List<lfm.Track>();

            // Make Method Run Asynchronously
            await Task.Run(() =>
            {
                XDocument x = XDocument.Parse(e);

                // Parse the similar artists list
                var tracks = from u in x.Descendants("track")
                             select new lfm.Track
                             {
                                 Name = u.SafeGetElement("name").SafeGetStringValue(),
                                 Duration = u.SafeGetElement("duration").SafeGetInt64Value(),
                                 Listeners = u.SafeGetElement("listeners").SafeGetInt64Value(),
                                 Playcount = u.SafeGetElement("playcount").SafeGetInt64Value(),
                                 URL = u.SafeGetElement("url").SafeGetUriValue(),
                                 Streamable = Converters.ToBool(u.SafeGetElement("streamable").SafeGetStringValue()),
                                 FullTrack = Converters.ToBool(u.SafeGetElement("streamable").SafeGetAttribute("fulltrack").SafeGetStringValue()),
                                 Artist = new lfm.Artist
                                 {
                                     Name = u.SafeGetElement("artist").SafeGetElement("name").SafeGetStringValue(),
                                     Url = u.SafeGetElement("artist").SafeGetElement("url").SafeGetUriValue()
                                 },
                                 Album = new lfm.Album
                                 {
                                     ImageSmall = u.Elements("image").Where(n => n.SafeGetAttribute("size").SafeGetStringValue() == "small").FirstOrDefault().SafeGetUriValue(),
                                     ImageMedium = u.Elements("image").Where(n => n.SafeGetAttribute("size").SafeGetStringValue() == "medium").FirstOrDefault().SafeGetUriValue(),
                                     ImageLarge = u.Elements("image").Where(n => n.SafeGetAttribute("size").SafeGetStringValue() == "large").FirstOrDefault().SafeGetUriValue(),
                                     ImageExtraLarge = u.Elements("image").Where(n => n.SafeGetAttribute("size").SafeGetStringValue() == "extralarge").FirstOrDefault().SafeGetUriValue()
                                 },
                                 PercentageChange = u.SafeGetElement("percentagechange").SafeGetStringValue()
                             };

                foreach (var s in tracks) result.Add(s);
            });

            // return the full artists
            return result;
        }
    }
}
